#!/usr/bin/env python3
"""
Generate a raw Environment Variables reference (Env_Vars.md) by scanning the codebase
for os.getenv / os.environ.get usages. Groups variables by common prefixes.

Usage:
  python Helper_Scripts/generate_env_vars_md.py

Writes Env_Vars.md at repo root.
"""

from __future__ import annotations

import os
import re
from pathlib import Path
from collections import defaultdict

REPO_ROOT = Path(__file__).resolve().parents[1]
SCAN_DIRS = [REPO_ROOT / "tldw_Server_API"]
OUT_PATH = REPO_ROOT / "Env_Vars.md"


ENV_PATTERNS = [
    re.compile(r"getenv\(\s*['\"]([A-Z0-9_]+)['\"]"),
    re.compile(r"os\.environ\.get\(\s*['\"]([A-Z0-9_]+)['\"]"),
]


GROUPS = [
    ("AuthNZ", ("AUTH_", "JWT_", "SINGLE_USER_", "ACCESS_TOKEN_", "REFRESH_TOKEN_", "ENABLE_REGISTRATION", "REQUIRE_REGISTRATION_CODE", "API_KEY", "API_BEARER")),
    ("Server & Security", ("tldw_production", "ENABLE_SECURITY_HEADERS", "ALLOWED_ORIGINS", "CORS_", "TRUSTED_", "EGRESS_")),
    ("Logging & OpenAPI", ("LOG_", "ENABLE_OPENAPI", "OPENAPI_", "FORCE_COLOR", "PY_COLORS")),
    ("Database & Storage", ("DATABASE_", "USER_DB_BASE_DIR", "USERS_DB_ENABLED", "CONTENT_DB_", "TLDW_DB_", "TLDW_SQLITE_", "CHROMADB_")),
    ("Jobs / Workers", ("JOBS_", "TLDW_JOBS_")),
    ("Workflows", ("WORKFLOWS_",)),
    ("Embeddings", ("EMBEDDINGS_", "EMB_")),
    ("RAG", ("RAG_",)),
    ("Chat & Providers", ("CHAT_", "DEFAULT_LLM_PROVIDER", "OPENAI_", "ANTHROPIC_", "COHERE_", "GROQ_", "GOOGLE_", "MISTRAL_", "QWEN_", "LLAMA_", "OLLAMA_", "VLLM_", "HUGGINGFACE_", "HF_")),
    ("Audio / TTS", ("AUDIO_", "TTS_", "ELEVENLABS_", "VIBEVOICE_", "HIGGS_", "CHATTERBOX_", "NEUTTS_")),
    ("OCR / VLM", ("OCR_", "DOTS_", "POINTS_", "VLM_")),
    ("Connectors", ("CONNECTOR_", "CONNECTORS_")),
    ("Watchlists", ("WATCHLISTS_",)),
    ("MCP & Metrics", ("METRICS_", "TRACES_", "OTEL_", "MCP_")),
    ("Paths & Misc", ("TLDW_", "TZ", "APP_", "DEPLOYMENT_ENV", "BASE_URL", "MAGIC_FILE_PATH")),
    ("Testing & CI", ("TEST_MODE", "TLDW_TEST_", "PYTEST_CURRENT_TEST", "CI", "RUN_", "E2E_")),
]


def collect_env_vars(paths: list[Path]) -> set[str]:
    names: set[str] = set()
    exts = {".py", ".md", ".html", ".js", ".ts", ".sh"}
    for base in paths:
        for root, _, files in os.walk(base):
            for fn in files:
                if Path(fn).suffix not in exts:
                    continue
                fp = Path(root) / fn
                try:
                    text = fp.read_text(encoding="utf-8", errors="ignore")
                except Exception:
                    continue
                for pat in ENV_PATTERNS:
                    for m in pat.finditer(text):
                        names.add(m.group(1))
    return names


def group_names(names: set[str]) -> tuple[dict[str, list[str]], list[str]]:
    groups: dict[str, list[str]] = defaultdict(list)
    remaining = set(names)
    # Assign by prefix patterns
    for group_name, prefixes in GROUPS:
        for n in sorted(list(remaining)):
            if any(n.startswith(p) for p in prefixes) or n in prefixes:
                groups[group_name].append(n)
                remaining.discard(n)
    return groups, sorted(list(remaining))


def write_markdown(all_names: set[str]) -> None:
    groups, leftovers = group_names(all_names)
    lines: list[str] = []
    lines.append("# Environment Variables - Raw Reference")
    lines.append("")
    lines.append("This file is auto-generated by `Helper_Scripts/generate_env_vars_md.py` by scanning the codebase for environment variable usage.")
    lines.append("It may include variables used only in tests or deprecated flags. When in doubt, prefer the curated documentation under `Docs/Published/Env_Vars.md`.")
    lines.append("")
    lines.append(f"Total detected variables: {len(all_names)}")
    lines.append("")
    for gname in [g[0] for g in GROUPS]:
        items = groups.get(gname, [])
        if not items:
            continue
        lines.append(f"## {gname}")
        lines.append("")
        for n in sorted(items):
            lines.append(f"- `{n}`")
        lines.append("")
    if leftovers:
        lines.append("## Other")
        lines.append("")
        for n in leftovers:
            lines.append(f"- `{n}`")
        lines.append("")
    OUT_PATH.write_text("\n".join(lines), encoding="utf-8")


def main() -> None:
    names = collect_env_vars(SCAN_DIRS)
    write_markdown(names)
    print(f"Wrote {OUT_PATH} with {len(names)} variables")


if __name__ == "__main__":
    main()
